package com.automannn.springPractice.applicationContext.bean.lookup;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.Map;
import java.util.stream.Stream;

/**
 * 注释配置应用程序作为ioc容器测试
 *
 * @author chenkh
 * @time 2021/8/20 11:35
 * @date 2022/08/03
 */
public class DCBeanTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(DCBeanTest.class);
        context.refresh();
        ConfigurableListableBeanFactory parentBeanFactory = context.getBeanFactory();
        HierarchicalBeanFactory beanFactory = (HierarchicalBeanFactory) parentBeanFactory.getBean("beanFactory");
        parentBeanFactory.setParentBeanFactory(beanFactory);
        displayLocalBean(parentBeanFactory, "user");
        displayLocalBean(beanFactory, "user");
        displayContainsBean(parentBeanFactory,"myA");
        context.close();
    }


    /**
     * 显示本地bean
     */
    public static void displayContainsBean(HierarchicalBeanFactory beanFactory, String name) {
        boolean b = containsBean(beanFactory, name);
        System.out.println("标志：" + b);
    }

    /**
     * 显示本地bean
     */
    public static boolean containsBean(HierarchicalBeanFactory beanFactory, String name) {
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory seanFactory = (HierarchicalBeanFactory) parentBeanFactory;
            if (containsBean(seanFactory, name)) {
                return true;
            }
        }
        return beanFactory.containsLocalBean(name);
    }

    /**
     * 显示本地bean
     */
    public static void displayLocalBean(HierarchicalBeanFactory beanFactory, String name) {
        System.out.println(String.format("当前beanfactory%s是否包含%s的结果%s", beanFactory.getClass(), name, beanFactory.containsLocalBean(name)));
    }


    @Bean
    public String helloWorld() {
        return "hello world";
    }

    @Bean(name = "user")
    public User getUser() {
        User user = new User();
        user.setName("1");
        user.setAge("11");
        return user;
    }

    @Bean(name = "superUser")
    public SuperUser getSuperUser() {
        SuperUser user = new SuperUser();
        user.setName("2");
        user.setAge("34");
        user.setAddres("崇贤");
        return user;
    }

    public static String lookUp(AnnotationConfigApplicationContext context) {
        ObjectProvider<String> beanProvider = context.getBeanProvider(String.class);
        return beanProvider.getObject();
    }

    public static void lookUpFoAnnotation(AnnotationConfigApplicationContext context) {
        if (context instanceof ListableBeanFactory) {
            Map<String, Object> beansWithAnnotation = context.getBeansWithAnnotation(Super.class);
            System.out.println(beansWithAnnotation);
        }
    }

    public static void lookUpFoAnnotationType(AnnotationConfigApplicationContext context) {
        if (context instanceof ListableBeanFactory) {
            ListableBeanFactory beanFactory = context.getBeanFactory();
            Map<String, User> beansWithAnnotation = beanFactory.getBeansOfType(User.class);
            String[] beanNamesForType = beanFactory.getBeanNamesForType(User.class);
            Stream.of(beanNamesForType).forEach(System.out::println);
            System.out.println(beansWithAnnotation);
        }
    }


    @Bean(name = "beanFactory")
    public HierarchicalBeanFactory getBeanFactory() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions("classpath:/xmlApplication.xml");
        return beanFactory;
    }
}
